/*

    矩形碰撞测试主函数，基于 SAT（分离轴）定理

 */

/** 比较两个矩形是否重叠 */
function isOverlap(r1, r2) {
    console.time('Overlap Test');
    try {
        if (!r1.rotate && !r2.rotate) {
            // 如果两个矩形都没有旋转，则使用正常的比较逻辑
            return normalRectangleOverlapTest(r1, r2);
        } else {
            // 有矩形旋转，使用分离轴测试
            return rotateRectangleOverlapTest(r1, r2);
        }
    } catch (err) {
        throw err;
    }
    finally {
        console.timeEnd('Overlap Test');
    }
}

/** 比较两个没有旋转的矩形 */
function normalRectangleOverlapTest(r1, r2) {
    const first = r1.y < r2.y ? r1 : r2,
        second = first === r2 ? r1 : r2;

    if (second.y >= first.y && second.y <= (first.y + first.height)) {
        if (second.x <= (first.x + first.width) && (second.x + second.width) >= first.x) {
            return true;
        }
    }
    return false;
}

/** 旋转矩形重叠检查 */
function rotateRectangleOverlapTest(r1, r2) {
    // 获取两个矩形的各顶点的真实坐标(即计算了矩形旋转后的顶点坐标)
    const rectVertex1 = r1.getRealVertex(),
        rectVertex2 = r2.getRealVertex();

    const { getVector } = common;

    // 检查各顶点以矩形1的 左上 --> 右上 向量为分离轴的投影是否重叠
    if (!SATTest(getVector(rectVertex1[0], rectVertex1[1]), rectVertex1, rectVertex2)) {
        return false;
    }

    // 检查各顶点以矩形1的 左上 --> 左下 向量为分离轴的投影是否重叠
    if (!SATTest(getVector(rectVertex1[0], rectVertex1[3]), rectVertex1, rectVertex2)) {
        return false;
    }

    // 检查各顶点以矩形2的 左上 --> 右上 向量为分离轴的投影是否重叠
    if (!SATTest(getVector(rectVertex2[0], rectVertex2[1]), rectVertex1, rectVertex2)) {
        return false;
    }

    // 检查各顶点以矩形2的 左上 --> 左下 向量为分离轴的投影是否重叠
    if (!SATTest(getVector(rectVertex2[0], rectVertex2[3]), rectVertex1, rectVertex2)) {
        return false;
    }

    return true;
}

/** 
 * 分离轴测试函数 
 * @param dirVector 分离轴的方向向量
 * @param rectVertex1 矩形1的各顶点坐标
 * @param rectVertex2 矩形2的各顶点坐标
 */
function SATTest(dirVector, rectVertex1, rectVertex2) {
    const { projection, rangeOverlap } = common;

    const axisProj1Rect1 = projection(dirVector, rectVertex1),
        axisProj1Rect2 = projection(dirVector, rectVertex2);

    return rangeOverlap(axisProj1Rect1, axisProj1Rect2);
}